﻿namespace Pathfinding
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using UnityEngine;

    [Serializable, AddComponentMenu("Pathfinding/Modifiers/Raycast Simplifier")]
    public class RaycastModifier : MonoModifier
    {
        public int iterations = 2;
        [HideInInspector]
        public LayerMask mask = -1;
        private static List<Vector3> nodes;
        [HideInInspector]
        public Vector3 raycastOffset = Vector3.zero;
        [HideInInspector]
        public bool subdivideEveryIter;
        [HideInInspector]
        public bool thickRaycast;
        [HideInInspector]
        public float thickRaycastRadius;
        [HideInInspector]
        public bool useGraphRaycasting;
        [HideInInspector]
        public bool useRaycasting = true;

        public override void Apply(Path p, ModifierData source)
        {
            if (this.iterations > 0)
            {
                if (nodes == null)
                {
                    nodes = new List<Vector3>(p.vectorPath.Count);
                }
                else
                {
                    nodes.Clear();
                }
                nodes.AddRange(p.vectorPath);
                for (int i = 0; i < this.iterations; i++)
                {
                    if (this.subdivideEveryIter && (i != 0))
                    {
                        if (nodes.Capacity < (nodes.Count * 3))
                        {
                            nodes.Capacity = nodes.Count * 3;
                        }
                        int count = nodes.Count;
                        for (int j = 0; j < (count - 1); j++)
                        {
                            nodes.Add(Vector3.zero);
                            nodes.Add(Vector3.zero);
                        }
                        for (int k = count - 1; k > 0; k--)
                        {
                            Vector3 from = nodes[k];
                            Vector3 to = nodes[k + 1];
                            nodes[k * 3] = nodes[k];
                            if (k != (count - 1))
                            {
                                nodes[(k * 3) + 1] = Vector3.Lerp(from, to, 0.33f);
                                nodes[(k * 3) + 2] = Vector3.Lerp(from, to, 0.66f);
                            }
                        }
                    }
                    int num5 = 0;
                    while (num5 < (nodes.Count - 2))
                    {
                        Vector3 vector3 = nodes[num5];
                        Vector3 vector4 = nodes[num5 + 2];
                        Stopwatch stopwatch = new Stopwatch();
                        stopwatch.Start();
                        if (this.ValidateLine(null, null, vector3, vector4))
                        {
                            nodes.RemoveAt(num5 + 1);
                        }
                        else
                        {
                            num5++;
                        }
                        stopwatch.Stop();
                    }
                }
                p.vectorPath.Clear();
                p.vectorPath.AddRange(nodes);
            }
        }

        public bool ValidateLine(GraphNode n1, GraphNode n2, Vector3 v1, Vector3 v2)
        {
            if (this.useRaycasting)
            {
                if (this.thickRaycast && (this.thickRaycastRadius > 0f))
                {
                    RaycastHit hit;
                    Vector3 vector = v2 - v1;
                    if (Physics.SphereCast(v1 + this.raycastOffset, this.thickRaycastRadius, v2 - v1, out hit, vector.magnitude, (int) this.mask))
                    {
                        return false;
                    }
                }
                else
                {
                    RaycastHit hit2;
                    if (Physics.Linecast(v1 + this.raycastOffset, v2 + this.raycastOffset, out hit2, (int) this.mask))
                    {
                        return false;
                    }
                }
            }
            if (this.useGraphRaycasting && (n1 == null))
            {
                n1 = AstarPath.active.GetNearest(v1).node;
                n2 = AstarPath.active.GetNearest(v2).node;
            }
            if ((this.useGraphRaycasting && (n1 != null)) && (n2 != null))
            {
                NavGraph graph = AstarData.GetGraph(n1);
                NavGraph graph2 = AstarData.GetGraph(n2);
                if (graph != graph2)
                {
                    return false;
                }
                if (graph != null)
                {
                    IRaycastableGraph graph3 = graph as IRaycastableGraph;
                    if ((graph3 != null) && graph3.Linecast(v1, v2, n1))
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        public override ModifierData input
        {
            get
            {
                return ModifierData.Vector;
            }
        }

        public override ModifierData output
        {
            get
            {
                return ModifierData.VectorPath;
            }
        }
    }
}

